(function($){

    function realFalse(v){
        return (typeof v === "boolean") && !v;
    }
    function isDisable(e){
        var event = e.onclick;
        if(event instanceof Function && realFalse(e.onclick())){
            return true;
        }
        if(e.getAttribute("disable") == "disable" || e.getAttribute("readonly") == "readonly"){
            return true;
        }
        return false;
    }
   $.fn.checkGroup = function(groupClass){
        var __that = this;
        var selector = "." + groupClass;

        function isAllChecked(){
            var allChecked = true;
            $(selector).each(function(){
                allChecked = allChecked && $(this).is(":checked");
            })
            return allChecked;
        }
        function checkAll(){
            $(selector).each(function(){
                this.checked = true;
            })
        }
        function cancelAllChecked(){
            $(selector).each(function(){
                this.checked = false;
            })
        }
        function refresh(){
            $(selector).on("click", function(){
                if(__that.length <= 0){
                    __that = $(__that.selector);
                }
                var event = this.onclick;
                if(event instanceof Function && realFalse(this.onclick())){
                    return;
                }
                __that[0].checked = isAllChecked();
            })
            __that.on("click", function(){
                var event = this.onclick;
                if(event instanceof Function && realFalse(this.onclick())){
                    return;
                }
                if(this.checked){
                    checkAll();
                }else {
                    cancelAllChecked();
                }
            })
            return __that;
        }
        function getValue(){
            var arr = [];
            $(selector).each(function(){
                if($(this).is(":checked")){
                    arr.push(this.value);
                }
            })
            return arr.join(",");
        }
        refresh();
        __that.refresh = refresh;
        __that.getValue = getValue;
        return __that;
   }

   function Node(e){
        this.children = [];
        this.parent = void(0);
        this.hasAllChecked = function(){
            var result = true;
            for(var i = 0; i < this.children.length; i++){
                result &= this.children[i].checked;
            }
            return result;
        }
        this.applyCheckState = function(){
            for(var i = 0; i <this.children.length; i++){
                this.children[i].setChecked(this.checked).applyCheckState();
            }
            return this;
        }
        this.refreshCheckState = function(){
            if(!this.parent){
                return;
            }
            var checkState = false;
            var allChecked = true;
            for(var i = 0; i < this.parent.children.length; i++){
                checkState |= this.parent.children[i].checked;
                allChecked &= this.parent.children[i].checked;
            }
            this.parent.setChecked(checkState);
            if(allChecked){
                this.parent.refreshCheckState();
            }
            return this;
        }

        this.setChecked = function(b){
            this.checked = b;
            e.checked = b;
            return this;
        }

        if(!e){
            return;
        }
        $(e).onclick = function(){
            this.setChecked(e.checked).applyCheckState().refreshCheckState();
        }

        this.id = $(e).data("id");
        this.pid = $(e).data("pid");
        this.checked = e.checked;
   }
   function Tree(){
        this.root = new Node();
        this.add = function(node){
            if(!node.pid){
                if(!!this.root){
                    node.children = this.root.children;
                }
                this.root = node;
            }else {
                var parent = search(this.root, node.pid);
                parent.children.push(node);
            }
        }
        function search(node, pid){
            if(node.id == pid){
                return node;
            }
            for(var i = 0; i < node.children.length; i++){
                var target = search(node.children[i], pid);
                if(!!target){
                    return target;
                }
            }
        }
        this.refresh = function(){
            this.root.refreshCheckState();
        }

   }

   $.fn.checkGroup2 = function(options){
        var defaults = {};
        var opts = $.extend({}, defaults, options);
        this.tree = new Tree();
        var __this = this;
        __this.refresh = function(){
            __this = $(__this.selector).checkGroup2().get();
            __this.tree = new Tree();
            __this.tree.add(new Node(this))
            __this.each(function(){
                __this.tree.add(new Node(this));
            })
        }
        __this.join = function(e){
            var node = new Node(e);
            __this.tree.add(node);
            node.refreshCheckState();
        }

        this.get = function(){
            return __this;
        }

        return __this;
   }
})($)